package com.cheng.xbjy.controller;

import com.cheng.xbjy.entity.User;
import com.cheng.xbjy.entity.vo.PageResult;
import com.cheng.xbjy.entity.vo.Result;
import com.cheng.xbjy.service.UserService;
import com.cheng.xbjy.util.LoginUserUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private HttpSession session;

    @Value("${spring.mail.username}")
    private String form;

    @Value("${filePath}")
    private String filePath;

    @Value("${uploadPath}")
    private String uploadPath;

    @Autowired
    private JavaMailSender mailSender;

    /**
     * 查看邮箱是否已被注册
     *
     * @param email
     * @return
     */
    @GetMapping("/checkEmail/{email}")
    public Result checkEmail(@PathVariable("email") String email) {
        User user = userService.findByEmail(email);
        if (user != null) {
            return new Result(false, "该邮箱已被注册");
        }
        return new Result(true, "邮箱没有被注册");
    }

    /**
     * 查看用户名是否已被注册
     *
     * @param username
     * @return
     */
    @GetMapping("/checkUsername/{username}")
    public Result checkUsername(@PathVariable("username") String username) {
        User user = userService.findByUsername(username);
        if (user != null) {
            return new Result(false, "该用户已被注册");
        }
        return new Result(true, "用户没有被注册");
    }

    /**
     * 注册用户
     *
     * @param user
     * @return
     */
    @PostMapping("/register")
    public Result register(@RequestBody User user) {
        userService.save(user);
        return new Result(true, "注册成功");
    }

    /**
     * 发送邮箱验证码
     *
     * @param email
     * @return
     */
    @PostMapping("/sendCode/{email}")
    public Result sendCode(@PathVariable("email") String email) {
        String code = (String) redisTemplate.opsForValue().get("user:updatePassword:code:" + email);
        if (StringUtils.isNotEmpty(code)) {
            return new Result(false, "60秒后才可以再次发送");
        }
        code = RandomStringUtils.randomNumeric(4);
        redisTemplate.opsForValue().set("user:updatePassword:code:" + email, code, 60, TimeUnit.SECONDS);
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(form);
        message.setTo(email);
        message.setSubject("您的验证码是:");
        message.setText(code);
        mailSender.send(message);
        return new Result(true, "发送成功");
    }

    /**
     * 修改密码
     *
     * @param code
     * @param user
     * @return
     */
    @PostMapping("/forget/{code}")
    public Result forget(@PathVariable("code") String code, @RequestBody User user) {
        String redisCode = (String) redisTemplate.opsForValue().get("user:updatePassword:code:" + user.getEmail());
        if (StringUtils.isNotEmpty(redisCode) && code.equals(redisCode)) {
            userService.updatePassword(user);
            //清空当前用户的缓存和session
            redisTemplate.delete("loginUser:" + LoginUserUtil.getUserId());
            session.invalidate();

            return new Result(true, "密码修改成功");
        }
        return new Result(false, "验证码错误");
    }

    /**
     * 用户登录
     *
     * @param code
     * @param user
     * @return
     */
    @PostMapping("/login/{code}")
    public Result login(@PathVariable("code") String code, @RequestBody User user) {
        //从session中获取code
        String sessionCode = (String) session.getAttribute("checkCode");
        if (StringUtils.isNotEmpty(sessionCode) && sessionCode.equals(code)) {
            user = userService.findOne(user);
            if (user != null) {
                //更新登入时间
                userService.updateLoginTime(user.getId());
                user.setPassword(null);
                //把用user存入redis中
                redisTemplate.opsForValue().set("loginUser:" + user.getId(), user, 30, TimeUnit.MINUTES);
                //把userId存入session
                session.setAttribute("userId", user.getId());
                return new Result(true, "登录成功", user);
            } else {
                return new Result(false, "用户名或密码错误");
            }
        } else {
            return new Result(false, "验证码错误");
        }
    }

    /**
     * 查看用户列表
     *
     * @param username
     * @param page
     * @return
     */
    @GetMapping("/findPageUser/{page}")
    public Result findPageUser(String username, @PathVariable("page") Integer page) {
        Page<User> pageData = userService.findPageUser(username, page);

        //查询当前用户关注过的人
        List<Long> focusIds = userService.findFocus(LoginUserUtil.getUserId());

        Map<String, Object> map = new HashMap<>();
        map.put("pageResult", new PageResult<User>(pageData.getTotalPages(), pageData.getContent()));
        map.put("focusIds", focusIds);
        return new Result(true, "查询成功", map);
    }

    /**
     * 根据id查询用户
     *
     * @param id
     * @return
     */
    @GetMapping("/detail/{id}")
    public Result detail(@PathVariable("id") Long id) {
        User user = userService.findById(id);
        //查询用户粉丝数
        Integer focus = userService.countFocusByUserId(id);

        //如果是当前登录用户自己查看自己，则不更新查看数
        if (!LoginUserUtil.getUserId().equals(id)) {
            userService.updateLookById(id);
        }

        user.setPassword(null);
        Map<String, Object> map = new HashMap<>();
        map.put("user", user);
        map.put("focus", focus);
        return new Result(true, "查询成功", map);
    }

    /**
     * 加关注或者取消关注
     *
     * @param focusId
     * @return
     */
    @GetMapping("/focus/{focusId}")
    public Result addFocus(@PathVariable("focusId") Long focusId) {
        Long userId = LoginUserUtil.getUserId();
        if (userId.equals(focusId)) {
            return new Result(false, "不可以关注自己");
        }
        return userService.addFocus(userId, focusId);
    }

    /**
     * 用户更新信息
     *
     * @param user
     * @return
     */
    @PutMapping("/update")
    public Result update(@RequestBody User user) {
        User dbUser = userService.update(user);
        dbUser.setPassword(null);
        redisTemplate.opsForValue().set("loginUser:" + dbUser.getId(), dbUser, 30, TimeUnit.MINUTES);
        return new Result(true, "更新成功", dbUser);
    }

    /**
     * 更新头像
     *
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadPic")
    public Result uploadPic(MultipartFile file) throws IOException {

        //解决同一文件夹下文件过多
        String dateName = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        File dir = new File(filePath + dateName);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        //获取文件名称
        String filename = file.getOriginalFilename();
        //截取文件类型(.png)
        assert filename != null;
        String type = filename.substring(filename.lastIndexOf('.'));
        String uuid = UUID.randomUUID().toString();

        //重新组装文件名(防止照片被覆盖)
        filename = uuid + type;

        //把图片写到硬盘中
        file.transferTo(new File(dir, filename));

        //文件网络地址
        String url = uploadPath + dateName + "/" + filename;

        //更新头像地址
        userService.updateUserPic(LoginUserUtil.getUserId(), url);

        User loginUser = LoginUserUtil.getLoginUser();
        assert loginUser != null;
        loginUser.setPic(url);

        //更新redis中的数据
        redisTemplate.opsForValue().set("loginUser:" + loginUser.getId(), loginUser);

        return new Result(true, "头像跟新成功", loginUser);
    }


    /**
     * 查询关注的用户列表
     *
     * @param page
     * @return
     */
    @GetMapping("/findFocusPage/{page}")
    public Result findFocusPage(@PathVariable("page") Integer page) {
        Page<User> pageList = userService.findFocusPage(LoginUserUtil.getUserId(), page);
        return new Result(true, "查询成功",
                new PageResult<User>(pageList.getTotalPages(), pageList.getContent()));
    }

    /**
     * 根据部门id查询该部门的所以员工
     *
     * @return
     */
    @GetMapping("/findDeptUser/{deptId}")
    public Result findDeptUser(@PathVariable("deptId") Long deptId) {
        return new Result(true, "查询成功", userService.findDeptUser(deptId));
    }


    /**
     * 用户退出
     *
     * @return
     */
    @GetMapping("/loginOut")
    public Result loginOut() {
        //删除redis中的信息
        redisTemplate.delete("loginUser:" + session.getAttribute("userId"));

        //清空session
        session.invalidate();
        return new Result(true, "退出成功");
    }
}
